import { Request, Response, NextFunction } from 'express';
import { AuthRequest } from '@/types';
import Role from '@/models/system/role.model';
import User from '@/models/system/user.model';
import RoleDept from '@/models/system/roleDept.model';
import Dept from '@/models/system/dept.model';

/**
 * 数据权限常量
 */
export const DATA_SCOPE = {
  /** 全部数据权限 */
  ALL: '1',
  /** 自定数据权限 */
  CUSTOM: '2',
  /** 部门数据权限 */
  DEPT: '3',
  /** 部门及以下数据权限 */
  DEPT_AND_CHILD: '4',
  /** 仅本人数据权限 */
  SELF: '5'
};

/**
 * 数据权限处理中间件
 * 处理数据范围权限，通过角色的数据范围设置，处理查询条件
 */
export const dataScopeMiddleware = () => {
  return async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {
    try {
      // 如果没有用户信息，则不进行数据权限过滤
      if (!req.user) {
        next();
        return;
      }
      
      // 如果是管理员，则不进行数据权限过滤
      if (req.user.userName === 'admin') {
        next();
        return;
      }
      
      // 获取用户信息
      const user = await User.findOne({
        where: { userId: req.user.userId },
        include: [
          {
            model: Role,
            where: { status: '0', delFlag: '0' },
            required: false
          }
        ]
      });
      
      if (!user) {
        next();
        return;
      }
      
      // 获取用户角色
      const roles = user.get('Roles') as Role[];
      
      // 如果没有角色，则只能查询自己的数据
      if (!roles || roles.length === 0) {
        // 设置数据权限条件为仅本人
        req.dataScope = generateDataScope(DATA_SCOPE.SELF, req.user.userId, user.deptId);
        next();
        return;
      }
      
      // 判断是否具有所有数据权限
      const hasAllDataScope = roles.some(role => role.dataScope === DATA_SCOPE.ALL);
      if (hasAllDataScope) {
        // 不进行数据权限过滤
        next();
        return;
      }
      
      // 获取用户的数据权限范围
      const dataScopeConditions: string[] = [];
      
      // 存储角色自定义数据权限的角色ID
      const customRoleIds: number[] = [];
      
      // 遍历角色的数据权限范围
      for (const role of roles) {
        // 自定义数据权限
        if (role.dataScope === DATA_SCOPE.CUSTOM) {
          customRoleIds.push(role.roleId);
          continue;
        }
        
        // 部门数据权限
        if (role.dataScope === DATA_SCOPE.DEPT) {
          const condition = `dept_id = ${user.deptId}`;
          if (!dataScopeConditions.includes(condition)) {
            dataScopeConditions.push(condition);
          }
          continue;
        }
        
        // 部门及以下数据权限
        if (role.dataScope === DATA_SCOPE.DEPT_AND_CHILD) {
          // 查询部门及其下级部门
          const dept = await Dept.findByPk(user.deptId);
          if (dept) {
            const condition = `dept_id = ${user.deptId} OR find_in_set(${user.deptId}, ancestors)`;
            if (!dataScopeConditions.includes(condition)) {
              dataScopeConditions.push(condition);
            }
          }
          continue;
        }
        
        // 仅本人数据权限
        if (role.dataScope === DATA_SCOPE.SELF) {
          const condition = `create_by = '${req.user.userName}'`;
          if (!dataScopeConditions.includes(condition)) {
            dataScopeConditions.push(condition);
          }
          continue;
        }
      }
      
      // 处理自定义数据权限
      if (customRoleIds.length > 0) {
        // 查询角色关联的部门
        const roleDepts = await RoleDept.findAll({
          where: {
            roleId: customRoleIds
          }
        });
        
        if (roleDepts.length > 0) {
          const deptIds = roleDepts.map(rd => rd.deptId);
          const condition = `dept_id IN (${deptIds.join(',')})`;
          dataScopeConditions.push(condition);
        }
      }
      
      // 设置数据权限SQL到请求对象中，供后续业务逻辑使用
      if (dataScopeConditions.length > 0) {
        req.dataScope = `(${dataScopeConditions.join(' OR ')})`;
      } else {
        // 如果没有配置数据权限，则默认只能查看自己的数据
        req.dataScope = generateDataScope(DATA_SCOPE.SELF, req.user.userId, user.deptId);
      }
      
      next();
      return;
    } catch (error) {
      console.error('数据权限过滤异常:', error);
      next(error);
      return;
    }
  };
};

/**
 * 生成数据权限SQL
 * @param dataScope 数据权限类型
 * @param userId 用户ID
 * @param deptId 部门ID
 * @param deptAlias 部门表别名，默认为空
 * @param userAlias 用户表别名，默认为空
 */
export function generateDataScope(
  dataScope: string,
  userId: number,
  deptId?: number,
  deptAlias: string = '',
  userAlias: string = ''
): string {
  const dept = deptAlias ? `${deptAlias}.` : '';
  const user = userAlias ? `${userAlias}.` : '';
  
  switch (dataScope) {
    case DATA_SCOPE.ALL:
      return '';
    case DATA_SCOPE.DEPT:
      if (deptId) {
        return `${dept}dept_id = ${deptId}`;
      }
      return `${user}create_by = '${userId}'`;
    case DATA_SCOPE.DEPT_AND_CHILD:
      if (deptId) {
        return `${dept}dept_id = ${deptId} OR find_in_set(${deptId}, ${dept}ancestors)`;
      }
      return `${user}create_by = '${userId}'`;
    case DATA_SCOPE.SELF:
    default:
      return `${user}create_by = '${userId}'`;
  }
} 